﻿using System;
using System.IO;

namespace LiskovSubstitutionLibrary
{
    public class ChildClass : BaseClass, IDirectInterface
    {
        protected new int HiddenField;

        private int _childClassState;

        public void NoOverride()
        {
            State = 1;
        }

        protected new void HiddenMethod()
        {
            State = 2;
        }

        public static void Foo()
        {
            Console.WriteLine("Foo");
        }

        public override void AbstractMethod()
        {
            throw new NotImplementedException();
        }

        public override void BaseInterfaceMethod()
        {
            throw new ArgumentNullException();
        }

        public void DirectInterfaceMethod()
        {
            throw new NotImplementedException();
        }

        public override int NoBaseCall(string text)
        {
            Console.WriteLine(text);
            return 0;
        }

        public override int GoodOverride(string text)
        {
            Console.WriteLine(text + _childClassState);
            return base.GoodOverride(text);
        }

        public override void ReturnBeforeBaseCall(string text)
        {
            if (DateTime.Now.Day == 4)
            {
                return;
            }
            base.ReturnBeforeBaseCall(text);
        }

        public override int ChangeOwnState(string text)
        {
            _childClassState = text.Length;
            return base.ChangeOwnState(text);
        }

        public override int ChangeBaseState(string text)
        {
            State = text.Length;
            return base.ChangeBaseState(text);
        }

        public override void ThrowBeforeBaseCall(string text)
        {
            if (DateTime.Now.Day == 4)
            {
                throw new ArgumentException();
            }
            base.ThrowBeforeBaseCall(text);
        }

        public override int ReturnOtherValue(string text)
        {
            return base.ReturnOtherValue(text) * 2;
        }

        public override Uri ReturnSameObject(string text)
        {
            var baseUri = base.ReturnSameObject(text);
            var childUri = new Uri(text + "test");
            Console.WriteLine(childUri);
            return baseUri;
        }

        public override Uri ReturnOtherObject(string text)
        {
            var baseUri = base.ReturnOtherObject(text);
            var childUri = new Uri(text + "test");
            Console.WriteLine(baseUri);
            return childUri;
        }

        public override int CalledBaseMethodModifiesBaseField(string text)
        {
            Console.WriteLine(text + _childClassState);
            base.HiddenMethod();
            return base.GoodOverride(text);
        }

        public override int CalledOwnMethodModifiesBaseField(string text)
        {
            var changeBaseState = ChangeBaseState(text);
            Console.WriteLine(text + changeBaseState);
            return base.GoodOverride(text);
        }

        public override void ThrowNewExceptionType()
        {
            try
            {
                base.ThrowNewExceptionType();
            }
            catch
            {
                throw new ArgumentException(HiddenField+" something");
            }
            Console.WriteLine("Hello World");
        }

        public override void ThrowBaseExceptionType()
        {
            try
            {
                base.ThrowBaseExceptionType();
            }
            catch
            {
                throw new FileLoadException(HiddenField + " something");
            }
            Console.WriteLine("Hello World");
        }

        public override void ThrowNewExceptionTypeInCall()
        {
            try
            {
                base.ThrowNewExceptionTypeInCall();
            }
            catch
            {
                ThrowArgumentException();
            }
            Console.WriteLine("Hello World");
        }

        private void ThrowArgumentException()
        {
            throw new ArgumentException(HiddenField + " something");
        }

        public override void ThrowBaseExceptionTypeInCall()
        {
            try
            {
                base.ThrowBaseExceptionTypeInCall();
            }
            catch
            {
                throw new FileLoadException(HiddenField + " something");
            }
            Console.WriteLine("Hello World");
        }

        public override int CopyLocal(string text)
        {
            int local1 = base.CopyLocal(text);
            Console.WriteLine(local1);
            int local2 = local1;
            Console.WriteLine(local2);
            return local2;
        }

        public override int CopyLocalReturnWrong(string text)
        {
            int local3 = 5;
            int local1 = base.CopyLocal(text);
            Console.WriteLine(local1);
            int local2 = local1;
            Console.WriteLine(local2);
            return local3;
        }
    }
}
